// 8. 属性修饰符
/*
readonly 只读属性           属性⽆法修改
public  公开的             可以在类、⼦类和对象中修改
protected 受保护的          可以在类、⼦类中修改
private 私有的             可以在类中修改
*/

// 9. 泛型
// 定义⼀个函数或类时，有些情况下⽆法确定其中要使⽤的具体类型（返回值、参数、属性的类型不能确 定），
// 此时就需要泛型了
// 举例： <T> 就是泛型，（不⼀定⾮叫 T ），设置泛型后即可在函数中使⽤ T 来表示该类型：
function test<T>(arg: T): T {
    return arg
}

// 不指名类型，TS会⾃动推断出来
console.log(test(20))

// 指名具体的类型
console.log(test<string>('diao mao'))
console.log(test<number>(90))

// 泛型可以写多个
function test2<T, U>(arg1: T, arg2: U): U {
    return arg2
}

// 为多个泛型指定具体⾃值
let x = test2<number, string>(96, 'hello')
console.log(x)

// 类中同样可以使⽤泛型：
class MyClass<T> {
    prop: T

    constructor(prop: T) {
        this.prop = prop
    }
}

// 也可以对泛型的范围进⾏约束
interface Demo{
    length:number
}

// 泛型T必须是MyInter的⼦类，即：必须拥有length属性
function test33<T extends Demo>(arg:T):number{
    return arg.length
}

// test33(10) // 类型“number”的参数不能赋给类型“Demo”的参数
// test33({name:'张三'}) // 类型“{ name: string; }”的参数不能赋给类型“Demo”的参数
console.log(test33('123'))
console.log(test33({name:'张三',length:10}))